package edu.zjut.hjg.saas.common.util;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.util.WebUtils;

public class CookieSessionUtil {
    private static Log          log                        = LogFactory
                                                                   .getLog(CookieSessionUtil.class);
    /** cookie的前缀 */
    private static final String COOKIE_SESSION_NAME_PREFIX = "_scp_";

    private String              COOKIE_PATH                = "/";

    /** cookie域名 */
    private String              cookieDomain               = null;

    /** 加密类 */
    private EncryptUtil         encryptUtil;

    /** 是否走https */
    private boolean             cookieSecurity             = false;

    /** 是否使用HttpOnly */
    private boolean             httpOnly                   = true;

    public void setCookieDomain(String cookieDomain) {
        this.cookieDomain = cookieDomain;
    }

    public void setEncryptUtil(EncryptUtil encryptUtil) {
        this.encryptUtil = encryptUtil;
    }

    public void setCookieSecurity(boolean cookieSecurity) {
        this.cookieSecurity = cookieSecurity;
    }

    public void setHttpOnly(boolean httpOnly) {
        this.httpOnly = httpOnly;
    }

    public <T> T getObjectFromCookieSession(String name, Class<T> clazz, HttpServletRequest request) {
        Cookie cookie = WebUtils.getCookie(request, COOKIE_SESSION_NAME_PREFIX + name);
        if (cookie == null) {
            return null;
        }
        try {
            // 解密
            return JsonUtil.fromJSON(encryptUtil.decrypt(cookie.getValue()), clazz);
        } catch (Exception e) {
            log.error("decrypt cookie based session failed: name=" + name, e);
            return null;
        }
    }

    public void saveObjectToCookieSession(String name, Object object, HttpServletResponse response) {
        // 加密
        String value;
        try {
            value = encryptUtil.encrypt(JsonUtil.toJSON(object));
        } catch (Exception e) {
            log.error("encrypt cookie based session failed: name=" + name + ",object=" + object, e);
            throw new RuntimeException("encrypt cookie based session failed: name=" + name
                    + ",object=" + object, e);
        }
        writeCookie(COOKIE_SESSION_NAME_PREFIX + name, value, response);
    }

    public void expireCookieSession(String name, HttpServletResponse response) {
        Cookie cookie = new Cookie(COOKIE_SESSION_NAME_PREFIX + name, "");
        if (cookieDomain != null) {
            // 为null就写到当前完整域下
            cookie.setDomain(cookieDomain);
        }
        cookie.setPath(COOKIE_PATH);
        cookie.setSecure(cookieSecurity);
        cookie.setMaxAge(0);
        response.addCookie(cookie);
    }

    private void writeCookie(String name, String value, HttpServletResponse response) {
        if (httpOnly) {
            String domain = "";
            if (cookieDomain != null) {
                if (cookieDomain.startsWith(".")) {
                    domain = ";Domain=" + cookieDomain;
                } else {
                    domain = ";Domain=." + cookieDomain;
                }
            }
            response.addHeader("Set-Cookie", name + "=" + value + domain + ";Path=" + COOKIE_PATH
                    + ";HttpOnly");
        } else {
            Cookie cookie = new Cookie(COOKIE_SESSION_NAME_PREFIX + name, value);
            if (cookieDomain != null) {
                // 为null就写到当前完整域下
                cookie.setDomain(cookieDomain);
            }
            // 浏览器关闭后失效
            cookie.setPath(COOKIE_PATH);
            cookie.setMaxAge(-1);
            cookie.setSecure(cookieSecurity);
            response.addCookie(cookie);
        }
    }
}
